---
import type { ProtectProps } from '../../types';

type Props = Omit<ProtectProps, 'condition'> & {
  class?: string;
  defaultSlotWrapperClass?: string;
  fallbackSlotWrapperClass?: string;
};

const {
  role,
  permission,
  feature,
  plan,
  class: className,
  defaultSlotWrapperClass,
  fallbackSlotWrapperClass,
} = Astro.props;
---

<clerk-protect
  data-role={role}
  data-permission={permission}
  data-feature={feature}
  data-plan={plan}
  class={className}
>
  <div
    class={defaultSlotWrapperClass}
    hidden
    data-clerk-control-slot-default
  >
    <slot />
  </div>
  <div
    class={fallbackSlotWrapperClass}
    hidden
    data-clerk-control-slot-fallback
  >
    <slot name='fallback' />
  </div>
</clerk-protect>

<script>
  import { $sessionStore } from '@clerk/astro/client';
  import { type AuthState, BaseClerkControlElement } from './BaseClerkControlElement';
  import type { CheckAuthorization } from '@clerk/shared/types';

  class ClerkProtect extends BaseClerkControlElement {
    private defaultSlot: HTMLDivElement | null = null;
    private fallbackSlot: HTMLDivElement | null = null;

    protected onAuthStateChange(state: AuthState): void {
      this.defaultSlot = this.querySelector('[data-clerk-control-slot-default]');
      this.fallbackSlot = this.querySelector('[data-clerk-control-slot-fallback]');

      const has = $sessionStore.get()?.checkAuthorization;

      const role = this.dataset.role;
      const permission = this.dataset.permission;
      const feature = this.dataset.feature;
      const plan = this.dataset.plan;
      const isUnauthorized =
        !state.userId ||
        ((role || permission || feature || plan) &&
          !has?.({ role, permission, feature, plan } as Parameters<CheckAuthorization>[0]));

      if (this.defaultSlot) {
        isUnauthorized ? this.defaultSlot.setAttribute('hidden', '') : this.defaultSlot.removeAttribute('hidden');
      }

      if (this.fallbackSlot) {
        isUnauthorized ? this.fallbackSlot.removeAttribute('hidden') : this.fallbackSlot.setAttribute('hidden', '');
      }
    }
  }

  customElements.define('clerk-protect', ClerkProtect);
</script>
